using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Networking;

public class CarControl : NetworkBehaviour
{
	public MortorType Type;

	public WheelCollider Wheel_FL;

	public WheelCollider Wheel_FR;

	public WheelCollider Wheel_RL;

	public WheelCollider Wheel_RR;

	public float[] GearRatio;

	public int CurrentGear;

	public float EngineTorque = 600f;

	public float MaxEngineRPM = 3000f;

	public float MinEngineRPM = 1000f;

	public float SteerAngle = 10f;

	public Transform COM;

	public float Speed;

	public float maxSpeed = 150f;

	public AudioSource skidAudio;

	public float EngineRPM;

	private float motorInput;

	public bool IsEngineStarted;

	private Vector2 inputAxis;

	private bool inputBrake;

	[SyncVar]
	public float steerAngleTemp;

	[SyncVar]
	private float audiopitch;

	private float latestMotorInput;

	public float NetworksteerAngleTemp
	{
		get
		{
			return steerAngleTemp;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref steerAngleTemp, 1u);
		}
	}

	public float Networkaudiopitch
	{
		get
		{
			return audiopitch;
		}
		[param: In]
		set
		{
			SetSyncVar(value, ref audiopitch, 2u);
		}
	}

	private void Start()
	{
		Rigidbody component = GetComponent<Rigidbody>();
		Vector3 localPosition = COM.localPosition;
		float x = localPosition.x;
		Vector3 localScale = base.transform.localScale;
		float x2 = x * localScale.x;
		Vector3 localPosition2 = COM.localPosition;
		float y = localPosition2.y;
		Vector3 localScale2 = base.transform.localScale;
		float y2 = y * localScale2.y;
		Vector3 localPosition3 = COM.localPosition;
		float z = localPosition3.z;
		Vector3 localScale3 = base.transform.localScale;
		component.centerOfMass = new Vector3(x2, y2, z * localScale3.z);
	}

	public void Controller(Vector2 input, bool brake)
	{
		inputAxis = input;
		inputBrake = brake;
	}

	private void Update()
	{
		if (base.isServer)
		{
			if ((bool)GetComponent<Rigidbody>())
			{
				GetComponent<Rigidbody>().isKinematic = false;
			}
			Speed = GetComponent<Rigidbody>().velocity.magnitude * 3.6f;
			GetComponent<Rigidbody>().drag = GetComponent<Rigidbody>().velocity.magnitude / 100f;
			EngineRPM = (Wheel_FL.rpm + Wheel_FR.rpm) / 2f * GearRatio[CurrentGear];
			if (!IsEngineStarted)
			{
				EngineRPM = 0f;
			}
			ShiftGears();
			motorInput = inputAxis.y;
			GetComponent<AudioSource>().pitch = Mathf.Abs(EngineRPM / MaxEngineRPM) + 1f;
			if (GetComponent<AudioSource>().pitch > 2f)
			{
				GetComponent<AudioSource>().pitch = 2f;
			}
			NetworksteerAngleTemp = SteerAngle * inputAxis.x;
			Wheel_FL.steerAngle = steerAngleTemp;
			Wheel_FR.steerAngle = steerAngleTemp;
			if (Speed > maxSpeed || !IsEngineStarted)
			{
				Wheel_RL.motorTorque = 0f;
				Wheel_RR.motorTorque = 0f;
				Wheel_FL.motorTorque = 0f;
				Wheel_FR.motorTorque = 0f;
			}
			else
			{
				switch (Type)
				{
				case MortorType.FourWheel:
					Wheel_FL.motorTorque = EngineTorque / GearRatio[CurrentGear] * inputAxis.y;
					Wheel_FR.motorTorque = EngineTorque / GearRatio[CurrentGear] * inputAxis.y;
					Wheel_RL.motorTorque = EngineTorque / GearRatio[CurrentGear] * inputAxis.y;
					Wheel_RR.motorTorque = EngineTorque / GearRatio[CurrentGear] * inputAxis.y;
					break;
				case MortorType.Front:
					Wheel_FL.motorTorque = EngineTorque / GearRatio[CurrentGear] * inputAxis.y;
					Wheel_FR.motorTorque = EngineTorque / GearRatio[CurrentGear] * inputAxis.y;
					break;
				case MortorType.Rear:
					Wheel_RL.motorTorque = EngineTorque / GearRatio[CurrentGear] * inputAxis.y;
					Wheel_RR.motorTorque = EngineTorque / GearRatio[CurrentGear] * inputAxis.y;
					break;
				}
			}
			if (latestMotorInput != motorInput || !IsEngineStarted)
			{
				Wheel_RL.brakeTorque = 10000f;
				Wheel_RR.brakeTorque = 10000f;
			}
			if (motorInput <= 0f)
			{
				Wheel_RL.brakeTorque = 0f;
				Wheel_RR.brakeTorque = 0f;
			}
			else if (motorInput >= 0f)
			{
				Wheel_RL.brakeTorque = 0f;
				Wheel_RR.brakeTorque = 0f;
			}
			if (inputBrake || !IsEngineStarted)
			{
				Wheel_RL.brakeTorque = 1000f;
				Wheel_RR.brakeTorque = 1000f;
			}
			if (!inputBrake)
			{
				Wheel_FL.brakeTorque = 0f;
				Wheel_FR.brakeTorque = 0f;
			}
			Wheel_RR.GetGroundHit(out WheelHit hit);
			if (Mathf.Abs(hit.sidewaysSlip) > 10f)
			{
				skidAudio.enabled = true;
			}
			else
			{
				skidAudio.enabled = false;
			}
			inputAxis = Vector2.zero;
			inputBrake = false;
			engineUpdate();
		}
		else
		{
			getengineUpdate();
			if ((bool)GetComponent<Rigidbody>())
			{
				GetComponent<Rigidbody>().isKinematic = true;
			}
		}
		latestMotorInput = motorInput;
	}

	public void engineUpdate()
	{
		if (GetComponent<AudioSource>().pitch > 2f)
		{
			GetComponent<AudioSource>().pitch = 2f;
		}
		Networkaudiopitch = GetComponent<AudioSource>().pitch;
		NetworksteerAngleTemp = Wheel_FL.steerAngle;
	}

	public void StartEngine(bool start)
	{
		IsEngineStarted = start;
	}

	public void getengineUpdate()
	{
		GetComponent<AudioSource>().pitch = audiopitch;
		Wheel_FL.steerAngle = steerAngleTemp;
	}

	private void ShiftGears()
	{
		int currentGear = CurrentGear;
		if (EngineRPM >= MaxEngineRPM)
		{
			for (int i = 0; i < GearRatio.Length; i++)
			{
				if (Wheel_FL.rpm * GearRatio[i] < MaxEngineRPM)
				{
					currentGear = i;
					break;
				}
			}
			CurrentGear = currentGear;
		}
		if (!(EngineRPM <= MinEngineRPM))
		{
			return;
		}
		currentGear = CurrentGear;
		for (int num = GearRatio.Length - 1; num >= 0; num--)
		{
			if (Wheel_FL.rpm * GearRatio[num] > MinEngineRPM)
			{
				currentGear = num;
				break;
			}
		}
		CurrentGear = currentGear;
	}

	private void UNetVersion()
	{
	}

	public override bool OnSerialize(NetworkWriter writer, bool forceAll)
	{
		if (forceAll)
		{
			writer.Write(steerAngleTemp);
			writer.Write(audiopitch);
			return true;
		}
		bool flag = false;
		if ((base.syncVarDirtyBits & 1) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(steerAngleTemp);
		}
		if ((base.syncVarDirtyBits & 2) != 0)
		{
			if (!flag)
			{
				writer.WritePackedUInt32(base.syncVarDirtyBits);
				flag = true;
			}
			writer.Write(audiopitch);
		}
		if (!flag)
		{
			writer.WritePackedUInt32(base.syncVarDirtyBits);
		}
		return flag;
	}

	public override void OnDeserialize(NetworkReader reader, bool initialState)
	{
		if (initialState)
		{
			steerAngleTemp = reader.ReadSingle();
			audiopitch = reader.ReadSingle();
			return;
		}
		int num = (int)reader.ReadPackedUInt32();
		if ((num & 1) != 0)
		{
			steerAngleTemp = reader.ReadSingle();
		}
		if ((num & 2) != 0)
		{
			audiopitch = reader.ReadSingle();
		}
	}
}
